import os
import json
from collections import OrderedDict
from PyQt5.QtCore import QThread, pyqtSignal
from PyQt5.QtWidgets import (QDialog,
        QDialogButtonBox, QGridLayout, QGroupBox, QComboBox,
        QLabel, QLineEdit, QPushButton, QTextEdit, QVBoxLayout, QFileDialog)
from PyQt5.QtGui import QColor, QIcon

import  icon_func

import time

class FuncionDialog(QDialog):

    def __init__(self, function, cfgpath, menuName, title, config={}, parent=None, threadlist=None):
        super(FuncionDialog, self).__init__(parent)
        self.function = function
        self.cfgpath = cfgpath
        self.parent_config = config
        self.config = config[menuName][title]
        self.setWindowTitle(title)
        self.initUI()
        self.buttonBox.button(QDialogButtonBox.Cancel).setText('取消')
        self.buttonBox.button(QDialogButtonBox.Ok).setText('运行')
        self.resize(400, 300)
        self.setWindowOpacity(0.95)
        self.threadlist = threadlist

    def initUI(self):
        self.setWindowIcon(QIcon(':/piggy-bank.ico'))
        intrStr = self.config["introduce"]
        self.intrGroupBox = QGroupBox("功能简介")
        self.intrGroupBox.setStyleSheet("font:255 9pt '新宋体'")
        intrText = QTextEdit(readOnly=True)
        intrText.setTextColor(QColor(255, 0, 0))
        intrText.setText(intrStr)
        intrText.setStyleSheet("background:rgb(0,0,0, 60);font:255 9pt '新宋体';border:gray")
        self.threadFunction = None

        layout = QVBoxLayout()
        layout.addWidget(intrText)
        self.intrGroupBox.setLayout(layout)

        params = self.config["configs"]
        self.cfgGroupBox = QGroupBox("输入参数")
        layout = QGridLayout()
        self.editorParams = OrderedDict()
        for i, param in enumerate(params, 1):
            arg = param['arg']
            name = param['name']
            qlabel = QLabel(name)
            qlabel.setStyleSheet("font:255 9pt '新宋体'")
            layout.addWidget(qlabel, i, 1)
            if 'combobox' in param and param['combobox']:
                combobox = eval(param['combobox'])
                editParam = QComboBox()
                if 'items' not in combobox:
                    combobox['items'] = combobox['params']
                editParam.addItems(combobox['items'])
                editParam.setCurrentIndex(combobox['index'])
                # for text in combobox:
                #     editParam.addItem(text)
            else:
                editParam = QLineEdit()
                if 'password' in param and param['password']:
                    editParam.setEchoMode(QLineEdit.Password)
                if 'default' in param:
                    editParam.setText(str(param['default']))
            if 'openFileDialog' in param:
                mode = param['openFileDialog']
                assert mode in ('file', 'directory')
                buttonName = "选择文件" if mode == 'file' else "选择文件夹"
                button = QPushButton(buttonName, self)
                # button.setStyleSheet('background: rgb(255, 232, 185)')
                button.setStyleSheet("QPushButton{color:black}"
                                                "QPushButton:hover{color:red}"
                                                "QPushButton{background-color:rgb(255,232,185, 200)}"
                                                #"QPushButton{border:2px}"
                                                #"QPushButton{border-radius:10px}"
                                                #"QPushButton{padding:2px 4px}"
                                                )
                button.clicked.connect(self.openfile(mode, editParam, button))
                layout.addWidget(button, i, 3)
                layout.addWidget(editParam, i, 2)
            else:
                layout.addWidget(editParam, i, 2, 1, 3)
            self.editorParams[arg] = (editParam, param)
        # self.cfgGroupBox.setStyleSheet('border: blue')
        self.cfgGroupBox.setLayout(layout)

        self.buttonBox = QDialogButtonBox(
            QDialogButtonBox.Ok | QDialogButtonBox.Cancel)

        self.buttonBox.accepted.connect(self.accept)
        self.buttonBox.rejected.connect(self.reject)

        mainLayout = QVBoxLayout()
        mainLayout.addWidget(self.intrGroupBox)
        mainLayout.addWidget(self.cfgGroupBox)
        mainLayout.addWidget(self.buttonBox)
        mainLayout.setStretchFactor(self.intrGroupBox, 1)
        mainLayout.setStretchFactor(self.cfgGroupBox, 3)
        mainLayout.setStretchFactor(self.buttonBox, 1)
        self.setLayout(mainLayout)
                
    def openfile(self, mode, editor, button):
        def _openfile():
            if mode == 'file':
                text = QFileDialog.getOpenFileName(button, "选择文件", editor.text(), 'All Files (*)')[0]
            else:
                text = QFileDialog.getExistingDirectory(button, "选择文件夹", editor.text(),)
            if text:
                editor.setText(text)
        return _openfile
            
    def accept(self):
        textParams = {}
        for arg, (editor, param) in self.editorParams.items():
            dtype = param['dtype']
            name = param['name']
            if 'combobox' in param:
                combobox = eval(param['combobox'])
                if 'items' not in combobox:
                    combobox['items'] = combobox['params']
                cmbdic = {k: v for k, v in zip(combobox['items'], combobox['params'])}
                text = editor.currentText()
                text = cmbdic[text]
            else:
                text = editor.text()
            if text == "":
                if '*' in name:
                    print("（%s）需要给定参数值." % name)
                    return
                else:
                    textParams[arg] = str(text)
                    param['default'] = str(text)
                    continue 
            try:
                if dtype == 'int':
                    text = int(text)
                elif dtype == 'float':
                    text = float(text)
                elif dtype == 'bool':
                    text = bool(eval(text))
                elif dtype == 'str':
                    text = r'%s' % text
            except:
                print('输入参数（%s: %s）错误!' % (dtype, text))
                return
            textParams[arg] = text
            param['default'] = str(text)
            if 'combobox' in param:
                cmbdic_ = {v: k for k, v in cmbdic.items()}
                combobox['index'] = combobox['items'].index(cmbdic_[str(text)])
                param['combobox'] = str(combobox)

        # self.function(**textParams)
        self.threadFunction = RunThread(self.function, textParams, parent=self, title=self.windowTitle())
        self.threadlist.append(self.threadFunction)
        self.threadFunction.start()
        
        self.printScriptConfig()
        super().accept()

    def printScriptConfig(self):
        config = OrderedDict(self.parent_config)
        with open(self.cfgpath, 'w', encoding='utf-8') as fp:
            json.dump(config, fp=fp, ensure_ascii=False)  
      
class RunThread(QThread):
    trigger = pyqtSignal()

    def __init__(self, function, kargs, parent=None, title=""):
        super(RunThread, self).__init__(parent=parent)
        self.function = function
        self.kargs = kargs
        self.title = title

    def __del__(self):
        self.wait()

    def run(self):
        try:
            if self.title:
                print("%s %s [开始]" % (time.strftime("%Y-%m-%d %H:%M:%S", time.localtime()), self.title))            
            self.function(**self.kargs)
            self.trigger.emit()
            # self.wait()
            print("%s %s [结束]\n" % (time.strftime("%Y-%m-%d %H:%M:%S", time.localtime()), self.title))
        except Exception as e:
            print("%s %s [异常]" % (time.strftime("%Y-%m-%d %H:%M:%S", time.localtime()), self.title))
            print(e)
        return 

if __name__ == '__main__':
    from PyQt5.QtWidgets import QApplication
    import sys

    app = QApplication(sys.argv)
    main = FuncionDialog()
    main.show()
    sys.exit(app.exec_())
